package cn.com.blueInfo.bpm.common.mybatisPlus;

import cn.com.blueInfo.bpm.common.enums.BaseDeleted;
import cn.com.blueInfo.bpm.common.enums.BaseStatus;
import cn.com.blueInfo.core.entity.CurrentLoginUserInfo;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

@Log4j2
@Component
public class MybatisMetaObjectHandler implements MetaObjectHandler {

    @Autowired
    private CurrentLoginUserInfo currentLoginUserInfo;
    /** 逻辑删除字段名(与application.yml中配置保持一致) */
    private static final String LOGIC_DELETE_FIELD = "deleted";

    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("开始插入填充");

        String orderNumber = "orderNumber";
        if (metaObject.hasGetter(orderNumber)) {
            this.strictInsertFill(metaObject, orderNumber, Integer.class, 1);
        }

        String tenantId = "tenantId";
        if (metaObject.hasGetter(tenantId)) {
            if (currentLoginUserInfo.getTenantId() != null) {
                this.strictInsertFill(metaObject, tenantId, Long.class, currentLoginUserInfo.getTenantId());
            } else {
                this.strictInsertFill(metaObject, tenantId, Long.class, -1L);
            }
        }

        String applicationId = "applicationId";
        if (metaObject.hasGetter(applicationId)) {
            if (currentLoginUserInfo.getApplicationId() != null) {
                this.strictInsertFill(metaObject, applicationId, Long.class, currentLoginUserInfo.getApplicationId());
            } else {
                this.strictInsertFill(metaObject, applicationId, Long.class, -1L);
            }
        }

        String status = "status";
        if (metaObject.hasGetter(status)) {
            this.strictInsertFill(metaObject, status, BaseStatus.class, BaseStatus.ENABLED);
        }

        String deleted = "deleted";
        if (metaObject.hasGetter(deleted)) {
            this.strictInsertFill(metaObject, deleted, BaseDeleted.class, BaseDeleted.NOT_DELETED);
        }

        String createUserId = "createUserId";
        if (metaObject.hasGetter(createUserId)) {
            Long userId = currentLoginUserInfo.getUserId();
            if (userId != null) {
                this.strictInsertFill(metaObject, createUserId, Long.class, userId);
            } else {
                String loginName = currentLoginUserInfo.getLoginName();
                if (StringUtils.isBlank(loginName)) {
                    this.strictInsertFill(metaObject, createUserId, Long.class, -1L);
                } else {
                    this.strictInsertFill(metaObject, createUserId, Long.class, 0L);
                }
            }
        }

        String createTime = "createTime";
        if (metaObject.hasGetter(createTime)) {
            this.strictInsertFill(metaObject, createTime, LocalDateTime.class, LocalDateTime.now());
        }
    }

    private boolean isLogicDeleteOperation(MetaObject metaObject, TableInfo tableInfo) {
        if (tableInfo == null) {
            return false;
        }

        // 获取逻辑删除字段名
        String logicDeleteField = tableInfo.getLogicDeleteFieldInfo() != null
                ? tableInfo.getLogicDeleteFieldInfo().getColumn()
                : LOGIC_DELETE_FIELD;

        // 检查是否更新了逻辑删除字段
        Object value = metaObject.getValue(logicDeleteField);
        if (value != null) {
            // 判断是否设置了逻辑删除值
            return BaseDeleted.DELETED.equals(value);
        }

        return false;
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("开始更新填充");
        Class<?> entityClass = metaObject.getOriginalObject().getClass();
        TableInfo tableInfo = TableInfoHelper.getTableInfo(entityClass);

        boolean isLogicDelete = isLogicDeleteOperation(metaObject, tableInfo);

        if (isLogicDelete) {
            String deleteUserId = "deleteUserId";
            if (metaObject.hasGetter(deleteUserId)) {
                Long userId = currentLoginUserInfo.getUserId();
                if (userId != null) {
                    this.strictUpdateFill(metaObject, deleteUserId, Long.class, userId);
                } else {
                    String loginName = currentLoginUserInfo.getLoginName();
                    if (StringUtils.isNotBlank(loginName)) {
                        this.strictUpdateFill(metaObject, deleteUserId, Long.class, -1L);
                    }
                }
            }

            String deleteTime = "deleteTime";
            if (metaObject.hasGetter(deleteTime)) {
                this.strictUpdateFill(metaObject, deleteTime, LocalDateTime.class, LocalDateTime.now());
            }
        }

        String tenantId = "tenantId";
        if (metaObject.hasGetter(tenantId)) {
            if (currentLoginUserInfo.getTenantId() != null) {
                this.strictUpdateFill(metaObject, tenantId, Long.class, currentLoginUserInfo.getTenantId());
            } else {
                this.strictUpdateFill(metaObject, tenantId, Long.class, -1L);
            }
        }

        String applicationId = "applicationId";
        if (metaObject.hasGetter(applicationId)) {
            if (currentLoginUserInfo.getApplicationId() != null) {
                this.strictUpdateFill(metaObject, applicationId, Long.class, currentLoginUserInfo.getApplicationId());
            } else {
                this.strictUpdateFill(metaObject, applicationId, Long.class, -1L);
            }
        }

        String updateUserId = "updateUserId";
        if (metaObject.hasGetter(updateUserId)) {
            Long userId = currentLoginUserInfo.getUserId();
            if (userId != null) {
                this.strictUpdateFill(metaObject, updateUserId, Long.class, userId);
            } else {
                String loginName = currentLoginUserInfo.getLoginName();
                if (StringUtils.isNotBlank(loginName)) {
                    this.strictUpdateFill(metaObject, updateUserId, Long.class, -1L);
                }
            }
        }

        String updateTime = "updateTime";
        if (metaObject.hasGetter(updateTime)) {
            this.strictUpdateFill(metaObject, updateTime, LocalDateTime.class, LocalDateTime.now());
        }
    }

}
